package vip.wangwenhao.sso.service.impl;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Service;
import vip.wangwenhao.autoconfigure.utils.Oauth2Utils;
import vip.wangwenhao.common.enums.ResultCode;
import vip.wangwenhao.common.result.Result;
import vip.wangwenhao.sso.service.TokenService;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;

/**
*  
*
* @author wwh
* @date 2020年01月15日 10:34
* 
*/

@Service
@Slf4j
public class TokenServiceImpl implements TokenService {

    @Autowired
    private TokenStore tokenStore;

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private ClientDetailsService clientDetailsService;

    @Resource
    @Qualifier("defaultTokenServices")
    private AuthorizationServerTokenServices authorizationServerTokenServices;

    @Value("${security.oauth2.client.client-id}")
    private String clientId;


    @Override
    public Result<JSONObject> login(HttpServletRequest request) {
        log.info("sessionId:{}",request.getSession().getId());
        String token = Oauth2Utils.getToken(request);
        if (StringUtils.isNotBlank(token)) {
            OAuth2Authentication oAuth2Authentication = tokenStore.readAuthentication(token);
            if (null == oAuth2Authentication) {
                return Result.fail(ResultCode.INVALID_TOKEN);
            }
            Object principal = oAuth2Authentication.getPrincipal();
            String username;
            if (principal instanceof User) {
                username = ((User) principal).getUsername();
            } else {
                username = String.valueOf(principal);
            }
            if (StringUtils.isNotBlank(username)) {
                UserDetails userDetails = userDetailsService.loadUserByUsername(username);
                if (null != userDetails) {
                    UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
                            new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                    usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                    //设置为已登录
                    SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
                    return Result.success(JSONObject.parseObject(JSONObject.toJSONString(usernamePasswordAuthenticationToken)));
                }else {
                    return Result.fail(ResultCode.INVALID_TOKEN,"username is not exist");
                }
            }else {
                return Result.fail(ResultCode.INVALID_TOKEN,"username is blank");
            }
        }
        return Result.fail(ResultCode.REQUEST_INVALID);
    }

    @Override
    public Result<OAuth2AccessToken> get(HttpServletRequest request, Authentication authentication) {
        String[] tokens = Oauth2Utils.isHasClientDetails(request);
        String clientId = tokens[0];
        ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);
        TokenRequest tokenRequest = new TokenRequest(new HashMap<>(4), clientId, clientDetails.getScope(), "custom");
        OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails);
        OAuth2Authentication auth2Authentication = new OAuth2Authentication(oAuth2Request, authentication);
        OAuth2AccessToken token = authorizationServerTokenServices.createAccessToken(auth2Authentication);
        return Result.success(token);
    }

    @Override
    public Result<OAuth2AccessToken> get(Authentication authentication) {
        ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);
        TokenRequest tokenRequest = new TokenRequest(new HashMap<>(4), clientId, clientDetails.getScope(), "custom");
        OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails);
        OAuth2Authentication auth2Authentication = new OAuth2Authentication(oAuth2Request, authentication);
        OAuth2AccessToken token = authorizationServerTokenServices.createAccessToken(auth2Authentication);
        return Result.success(token);
    }
}